package com.eflow.engine.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.eflow.engine.service.IEflowRepositoryServiceService;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @CLASSNAME IEflowBpmModeService
 * @Description
 * @Auther JanHezz
 * @BLOG www.luckyhe.com
 * @DATE 2021/3/4 10:35
 */
public class EflowRepositoryServiceImpl extends AbstractEflowService implements IEflowRepositoryServiceService {



      @Override
    public BpmnModel getBpmnModelByProcessDefId(String processDefId) {
        return repositoryService.getBpmnModel(processDefId);
    }

      @Override
    public ProcessDefinition getProcessDefinitionByProcessDefId(String processDefId) {
               return repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefId)
                   .singleResult();

    }


     @Override
     public List<FlowNode> findFlowNodes(String processDefId) {
        List<FlowNode> flowNodes = new ArrayList<>();
        BpmnModel bpmnModel = this.getBpmnModelByProcessDefId(processDefId);
        Process process = bpmnModel.getMainProcess();
        Collection<FlowElement> list = process.getFlowElements();
        list.forEach(flowElement -> {
            if (flowElement instanceof FlowNode) {
                flowNodes.add((FlowNode) flowElement);
            }
        });
        return flowNodes;
    }


    @Override
    public List<EndEvent> findEndFlowElement(String processDefId) {
        BpmnModel bpmnModel = this.getBpmnModelByProcessDefId(processDefId);
        if (bpmnModel != null) {
            Process process = bpmnModel.getMainProcess();
            return process.findFlowElementsOfType(EndEvent.class);
        } else {
            return null;
        }
    }
    protected FlowNode findMainProcessActivityByActivityId(String processDefId, String activityId) {
        FlowNode activity = null;
        BpmnModel bpmnModel = this.getBpmnModelByProcessDefId(processDefId);
        Process process = bpmnModel.getMainProcess();
        FlowElement flowElement = process.getFlowElement(activityId);
        if (flowElement != null) {
            activity = (FlowNode) flowElement;
        }
        return activity;
    }


    @Override
    public FlowNode findFlowNodeByActivityId(String processDefId, String activityId, Boolean isMain) {

        if (isMain) {
            return findMainProcessActivityByActivityId(processDefId
                    , activityId);
        }
        return findFlowNodeByActivityId(processDefId

                , activityId);
    }

     protected FlowNode findFlowNodeByActivityId(String processDefId, String activityId) {
        FlowNode activity = null;
        BpmnModel bpmnModel = this.getBpmnModelByProcessDefId(processDefId);
        Process process = bpmnModel.getMainProcess();
        FlowElement flowElement = process.getFlowElement(activityId);
        if (flowElement != null) {
            activity = (FlowNode) flowElement;
        }
        return activity;
    }


    @Override
    public boolean checkActivitySubprocessByActivityId(String processDefId, String activityId) {
        boolean flag = true;
        List<FlowNode> activities = this.findFlowNodesByActivityId(processDefId,activityId);
        if (CollectionUtils.isNotEmpty(activities)){
            flag = false;
        }
        return flag;
    }

    public List<FlowNode> findFlowNodesByActivityId(String processDefId, String activityId) {
        List<FlowNode> activities = new ArrayList<>();
        BpmnModel bpmnModel = this.getBpmnModelByProcessDefId(processDefId);
        List<Process> processes = bpmnModel.getProcesses();
        for (Process process : processes) {
            FlowElement flowElement = process.getFlowElement(activityId);
            if (flowElement != null) {
                FlowNode flowNode = (FlowNode) flowElement;
                activities.add(flowNode);
            }
        }
        return activities;
    }


    @Override
    public FlowNode findFlowNodeByName(String processDefId, String name) {
        FlowNode node = null;
        BpmnModel bpmnModel = this.getBpmnModelByProcessDefId(processDefId);
        Process process = bpmnModel.getMainProcess();
        Collection<FlowElement> list = process.getFlowElements();
        for (FlowElement f : list) {
            if (!StringUtils.isEmpty(name)) {
                if (name.equals(f.getName())) {
                    node = (FlowNode) f;
                    break;
                }
            }
        }
        return node;
    }
}
